// eee.Sheffield.PZ.Imaging
//
// Copyright ?Ping Zou, 2007
// sg71.cherub@gmail.com

using System;
using System.Collections.Generic;
using System.Text;
using eee.Sheffield.PZ.Math;
using System.Drawing;
using System.Drawing.Imaging;

namespace eee.Sheffield.PZ.Imaging.ImageFilter
{
    public class MCMCGVFThinning : ImageFilter
    {
        //#region Flag
        //private string flag = "[Image -> Morphology -> GVFThinning]";
        //public string Flag() { return flag; }
        //#endregion

        #region Fields
        // RJMCMC exampler
        private MCMCGVFThinningSampler _sampler;    // MCMC sampler
        private int _total;                         // total MCMC iterations
        private int _burnin;                    // burn in iterations
        private int _space;                // sample space
       
        // data term
        private Bitmap _srcImage;
        private PZMath_matrix _gvfU;
        private PZMath_matrix _gvfV;
        private PZMath_matrix _gvfMagnitude;

        // line segment configurations
        private LineSegmentConfiguration _pool;
        //private List<LineSegmentConfiguration> _lineSegmentConfigurationSamples;
        #endregion

        #region Properties
        public int Total { get { return _total; } set { _total = value; } }
        public int BurnIn { get { return _burnin; } set { _burnin = value; } }
        public int Space { get { return _space; } set { _space = value; } }
        public MCMCGVFThinningSampler Sampler { get { return _sampler; } }
        //public List<LineSegmentConfiguration> LineSegmentConfigurationSamples { get { return _lineSegmentConfigurationSamples; } }
        #endregion

        #region Constructor
        public MCMCGVFThinning(Bitmap srcImage, PZMath_matrix gvfU, PZMath_matrix gvfV, PZMath_matrix gvfMagnitude, LineSegmentConfiguration allLineSegmentConfiguration,
            int total, int burin, int space)
        {
            _srcImage = srcImage;
            _gvfU = gvfU;
            _gvfV = gvfV;
            _gvfMagnitude = gvfMagnitude;
            _pool = allLineSegmentConfiguration;
            _total = total;
            _burnin = burin;
            _space = space;

            _sampler = new MCMCGVFThinningSampler(_total, _burnin, _space, _pool);
            //_sampler.LogWriter = _logWriter;
            _flag = "[Image -> Morphology -> GVFThinning]";
        }
        #endregion

        //#region initialize method
        //private void Init(int N, int n0, int space)
        //{
        //    _sampler = new MCMCGVFThinningSampler(N, n0, );
        //}
        //#endregion

        #region override methods
        protected override PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix, out string logText)
        {
            _sampler.Sample();
            // return line segments' hitting probability map
            //PZMath_matrix dstMatrix = GetLineSegmentHittingProbabilityMap(_lineSegmentConfigurationSamples, _srcImage);
            PZMath_matrix dstMatrix = GetLineSegmentHittingProbabilityMap(_sampler.MCMCStateInstance.HitRecord, _srcImage);

            logText = "success";
            return dstMatrix;
        }

        protected override PZMath_matrix[] ApplyDoubleColourImageFilter(PZMath_matrix[] srcMatrixArray, out string logText)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        //public Bitmap Apply()
        //{            
        //    // prepare target distribution
        //    TargetDistribution targetDistribution = new TargetDistribution();
        //    targetDistribution.TargetDensityFunction = new targetDensityFunction(GVFThinningSampler.ExampleDensityFunction);

        //    // assign target distribution and instrumental distribution to the work space
        //    _sampler.GMTargetDistribution = targetDistribution;

        //    // M-H sample
        //    _sampler.Init(_pool);
        //    List<LineSegmentConfiguration> samples = _sampler.Sample();
        //    int returnIndex = _sampler.IndexMax;            
        //    return samples[returnIndex].DrawLineSegments(_srcImage);                
        //} // Apply()
        #endregion

        #region generate results
        /// <summary>
        /// get line segments' hitting probability map, in gray-level
        /// </summary>
        /// <param name="lineSegmentConfigurationSamples"></param>
        /// <param name="srcImage"></param>
        /// <returns></returns>
        private PZMath_matrix GetLineSegmentHittingProbabilityMap(List<LineSegmentConfiguration> lineSegmentConfigurationSamples, Bitmap srcImage)
        {
            int sampleCount = lineSegmentConfigurationSamples.Count;
            int width = srcImage.Width;
            int height = srcImage.Height;
            PZMath_matrix dstMatrix = new PZMath_matrix(height, width);
            dstMatrix.Setall(0.0);
            for (int i = 0; i < sampleCount; i++)
            // for each line segment configuration
            {
                LineSegmentConfiguration lineSegmentConfiguration = (LineSegmentConfiguration)lineSegmentConfigurationSamples[i];
                int lineSegmentCount = lineSegmentConfiguration.N;
                for (int j = 0; j < lineSegmentCount; j++)
                // for each line segment
                {
                    LineSegment lineSegment = (LineSegment)lineSegmentConfiguration.Configure[j];
                    int pointCount = lineSegment.Ls;
                    for (int k = 0; k < pointCount; k++)
                    // for each point
                    {
                        int x = (int)lineSegment.PointList[k].x;
                        int y = (int)lineSegment.PointList[k].y;
                        dstMatrix[y, x]++;
                    }
                }
            }
            dstMatrix.Normalize(0, 255);

            return dstMatrix;
        } // GetLineSegmentHittingProbabilityMap()


        private PZMath_matrix GetLineSegmentHittingProbabilityMap(LineSegmentConfiguration sourceLineSegmentConfiguration, Bitmap srcImage)
        {            
            int width = srcImage.Width;
            int height = srcImage.Height;
            PZMath_matrix dstMatrix = new PZMath_matrix(height, width);
            dstMatrix.Setall(0.0);
            for (int i = 0; i < sourceLineSegmentConfiguration.N; i++)
            // for each line segment configuration
            {
                LineSegment l = (LineSegment)sourceLineSegmentConfiguration.Configure[i];
                int pointCount = l.Ls;

                for (int k = 0; k < pointCount; k++)
                // for each point
                {
                    int x = (int)l.PointList[k].x;
                    int y = (int)l.PointList[k].y;
                    dstMatrix[y, x] += l.Hit;
                }

            }
            dstMatrix.Normalize(0, 255);
            return dstMatrix;
        }
        #endregion

    }
}
